/*
 * File:   parser.cpp
 * Author: dolphinigle
 *
 * Created on December 1, 2011, 3:50 PM
 */

#include "parser.h"

#include "engine.h"
#include "util.h"

#include <string>
#include <vector>

using std::string;
using std::vector;

string Parser::Execute(string query) {
  // Split query into space-separated tokens.
  vector<string> queries = StringSplit(query, ' ');

  if ((int)queries.size() == 0) {
    return "No query entered.";
  }

  if (queries[0] == "format") {
    string err_msg = "Syntax for format: format @[file] [size_in_bytes]";
    if ((int)queries.size() != 3) {
      return err_msg;
    }
    Path arg1(queries[1]);
    int arg2 = atoi(queries[2].c_str());

    if (arg1.is_virtual() || arg2 <= 0 || !IsFileName(arg1.path())) {
      return err_msg;
    }

    return engine_->Format(arg1, arg2);
  } else if (queries[0] == "mountfs") {
    string err_msg = "Syntax for mountfs: mountfs @[file] [mount location]";
    if ((int)queries.size() != 3) {
      return err_msg;
    }

    Path arg1(queries[1]);
    Path arg2(queries[2]);

    if (arg1.is_virtual() || !arg2.is_virtual() || !IsFileName(arg1.path()) ||
            !IsDirectoryName(arg2.path())) {
      return err_msg;
    }

    return engine_->MountFS(arg1, arg2);
  } else if (queries[0] == "umount") {
    string err_msg = "Syntax for umount: umount [mount point]";
    if ((int)queries.size() != 2) {
      return err_msg;
    }

    Path arg1(queries[1]);

    if (!arg1.is_virtual() || !IsDirectoryName(arg1.path())) {
      return err_msg;
    }

    return engine_->Unmount(arg1);
  } else if (queries[0] == "pwd") {
    string err_msg = "Syntax for pwd: pwd";
    if ((int)queries.size() != 1) {
      return err_msg;
    }

    return engine_->Pwd();
  } else if (queries[0] == "ls") {
    string err_msg = "Syntax for mountfs: ls <directory>";
    if ((int)queries.size() != 1 && (int)queries.size() != 2) {
      return err_msg;
    }

    if (queries.size() == 1) return engine_->Ls();

    Path arg1(queries[1]);

    if (!arg1.is_virtual() || !IsDirectoryName(arg1.path())) {
      return err_msg;
    }

    return engine_->LsDirectory(arg1);
  } else if (queries[0] == "cd") {
    string err_msg = "Syntax for cd: cd [directory]";
    if ((int)queries.size() != 2) {
      return err_msg;
    }

    Path arg1(queries[1]);

    if (!arg1.is_virtual() || !IsDirectoryName(arg1.path())) {
      return err_msg;
    }

    return engine_->Cd(arg1);
  } else if (queries[0] == "mkdir") {
    string err_msg = "Syntax for mkdir: mkdir [directory]";
    if ((int)queries.size() != 2) {
      return err_msg;
    }

    Path arg1(queries[1]);

    if (!arg1.is_virtual() || !IsDirectoryName(arg1.path())) {
      return err_msg;
    }

    return engine_->Mkdir(arg1);
  } else if (queries[0] == "rm") {
    string err_msg = "Syntax for rm: rm [file/directory]";
    if ((int)queries.size() != 2) {
      return err_msg;
    }

    Path arg1(queries[1]);

    if (!arg1.is_virtual()) {
      return err_msg;
    }

    return engine_->Rm(arg1);
  } else if (queries[0] == "cp") {
    string err_msg = "Syntax for cp: cp <@>[file/folder] <@>[file/folder]";
    if ((int)queries.size() != 3) {
      return err_msg;
    }

    Path arg1(queries[1]);
    Path arg2(queries[2]);

    if (!arg1.is_virtual() && !arg2.is_virtual()) {
      return err_msg;
    }

    return engine_->Cp(arg1, arg2);
  } else if (queries[0] == "mv") {
    string err_msg = "Syntax for mv: mv <@>[file/folder] <@>[file/folder]";
    if ((int)queries.size() != 3) {
      return err_msg;
    }

    Path arg1(queries[1]);
    Path arg2(queries[2]);

    if (!arg1.is_virtual() && !arg2.is_virtual()) {
      return err_msg;
    }

    return engine_->Mv(arg1, arg2);
  } else if (queries[0] == "cat") {
    string err_msg = "Syntax for cat: cat [file]";
    if ((int)queries.size() != 2) {
      return err_msg;
    }

    Path arg1(queries[1]);

    if (!arg1.is_virtual() || !IsFileName(arg1.path())) {
      return err_msg;
    }

    return engine_->Cat(arg1);
  } else if (queries[0] == "status") {
    string err_msg = "Syntax for status: status";
    if ((int)queries.size() != 1) {
      return err_msg;
    }

    return engine_->Status();
  } else if (queries[0] == "exit") {
    string err_msg = "Syntax for exit: exit";
    if ((int)queries.size() != 1) {
      return err_msg;
    }

    return engine_->Exit();
  } else {
    return "Unrecognized Command: " + queries[0];
  }
}

vector<string> Parser::StringSplit(string input_str, char separator) {
  input_str += separator;
  vector<string> ret;
  string running_sum = "";
  for (int i = 0; i < input_str.length(); ++i) {
    if (input_str[i] == separator) {
      if (running_sum != "") {
        ret.push_back(running_sum);
      }
      running_sum = "";
      continue;
    }
    running_sum += input_str[i];
  }

  return ret;
}

